package com.xiaoxu.intranetweb.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.xml.soap.*;
import java.io.ByteArrayOutputStream;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Slf4j
public class WebServiceClient {
    private static final String NAMESPACE_URI = "http://shuto.com/mam/webservice/common/service/commonservice";
    private final AtomicInteger connectionCounter = new AtomicInteger(0);
    private static final int MAX_CONNECTIONS = 100; // 防止连接泄漏的阈值

    // 新增定时任务管理器
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
    private final ConcurrentHashMap<SOAPConnection, Future<?>> connectionTimeoutMap = new ConcurrentHashMap<>();
    private final ReferenceQueue<SOAPConnection> referenceQueue = new ReferenceQueue<>();

    /**
     * 增强的 WebService 调用方法，每次调用创建新连接
     */
    public String callWebService(String wsdlUrl, String soapAction, String xmlData) throws Exception {
        checkConnectionHealth();

        SOAPConnection soapConnection = null;
        try {
            connectionCounter.incrementAndGet();

            // 每次调用都创建新的 SOAP 连接
            soapConnection = SOAPConnectionFactory.newInstance().createConnection();

            // 注册超时关闭任务 (5秒后执行)
            registerAutoCloseTask(soapConnection);

            // 创建并发送SOAP消息
            SOAPMessage soapMessage = createSoapMessage(soapAction, xmlData);
            SOAPMessage response = soapConnection.call(soapMessage, new URL(wsdlUrl));

            return convertResponseToString(response);
        } catch (SOAPException e) {
            throw new SOAPException("WebService调用失败，可能需要重置状态", e);
        } finally {
            // 优先执行手动关闭（会取消自动关闭任务）
            closeConnection(soapConnection);
            connectionCounter.decrementAndGet();
        }
    }

    /**
     * 安全的连接关闭方法（支持手动/自动两种模式）
     */
    private void closeConnection(SOAPConnection connection) {
        if (connection != null) {
            try {
                // 取消自动关闭任务
                cancelAutoCloseTask(connection);
                // 立即关闭连接
                connection.close();
            } catch (Exception e) {
                // 记录但忽略关闭异常
            }
        }
    }

    /**
     * 注册自动关闭任务（5秒后执行）
     */
    private void registerAutoCloseTask(SOAPConnection connection) {
        // 创建弱引用防止内存泄漏
        PhantomReference<SOAPConnection> ref = new PhantomReference<>(connection, referenceQueue);

        // 创建延迟任务
        Future<?> future = scheduler.schedule(() -> {
            try {
                connection.close();
                log.error("连接超过5秒网络不稳定");
            } catch (Exception e) {
                log.error("关闭连接错误", e);
            } finally {
                connectionTimeoutMap.remove(connection);
            }
        }, 5, TimeUnit.SECONDS);

        // 存入映射表用于后续取消
        connectionTimeoutMap.put(connection, future);
    }

    /**
     * 取消自动关闭任务
     */
    private void cancelAutoCloseTask(SOAPConnection connection) {
        Future<?> future = connectionTimeoutMap.remove(connection);
        if (future != null && !future.isDone()) {
            future.cancel(true);
        }
    }

    /**
     * 真正的重置方法
     */
    public synchronized void reset() {
        try {
            // 重置计数器
            connectionCounter.set(0);

            // 清理残留的连接引用
            while (true) {
                Reference<? extends SOAPConnection> ref = referenceQueue.poll();
                if (ref == null) break;
                // GC会自动回收被引用的对象
            }

            System.gc(); // 建议JVM清理，但不是必须的
        } catch (Exception e) {
            // 重置过程中的异常不应该影响主流程
        }
    }


    /**
     * 检查连接健康状态
     */
    private void checkConnectionHealth() throws SOAPException {
        if (connectionCounter.get() > MAX_CONNECTIONS) {
            reset();
            throw new SOAPException("连接数超过阈值，已自动重置");
        }
    }

    /**
     * 创建SOAP连接
     */
    private SOAPConnection createSoapConnection() throws SOAPException {
        return SOAPConnectionFactory.newInstance().createConnection();
    }

    /**
     * 创建SOAP消息
     */
    private SOAPMessage createSoapMessage(String soapAction, String xmlData) throws Exception {
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();

        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.setPrefix("soapenv");
        envelope.addNamespaceDeclaration("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
        envelope.addNamespaceDeclaration("com", NAMESPACE_URI);

        SOAPBody soapBody = envelope.getBody();
        soapBody.setPrefix("soapenv");
        SOAPElement uploadElement = soapBody.addChildElement("upload", "com");
        SOAPElement in0Element = uploadElement.addChildElement("in0", "com");

        Text cdataNode = (Text) soapBody.getOwnerDocument().createCDATASection(xmlData);
        in0Element.appendChild(cdataNode);

        soapMessage.getMimeHeaders().addHeader("SOAPAction", soapAction);
        return soapMessage;
    }

    /**
     * 转换响应为字符串
     */
    private String convertResponseToString(SOAPMessage response) throws Exception {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        response.writeTo(out);
        return out.toString(StandardCharsets.UTF_8.name());
    }
}